using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using XcoAppSpaces.Transport.Sockets.Auth;
using XcoAppSpaces.Transport.Sockets.Auth.Contract;
using System.Threading.Tasks;
using System.Threading;
using System.Net.Sockets;

namespace test.XcoAppSpaces.Transport.Sockets.Auth
{
	[TestFixture]
	public class CheckIpBlacklistTests
	{
		private CheckIpBlacklist sut;
		private TcpClient resultAllowedConnection;
		private TcpClient resultBlockedConnection;

		[SetUp]
		public void SetUp()
		{
			sut = new CheckIpBlacklist(3, 1000);
			sut.Out_AllowedConnection += _ => resultAllowedConnection = _;
			sut.Out_BlockedConnection += _ => resultBlockedConnection = _;
			resultAllowedConnection = null;
			resultBlockedConnection = null;
		}

		[Test]
		public void AddressOnBlacklistIsBlocked()
		{
			using (var connections = new ConnectedTcpClientPair())
			{
				sut.In_InvalidAddress(connections.ReceivingClient.Client.RemoteEndPoint);

				sut.In_Connection(connections.ReceivingClient);
				
				Assert.IsTrue(SpinWait.SpinUntil(() => resultBlockedConnection != null, 1000));
				Assert.AreSame(connections.ReceivingClient, resultBlockedConnection);
			}
		}

		[Test]
		public void AddressNotOnBlacklistIsAllowed()
		{
			using (var connections = new ConnectedTcpClientPair())
			{
				sut.In_Connection(connections.ReceivingClient);

				Assert.IsTrue(SpinWait.SpinUntil(() => resultAllowedConnection != null, 1000));
				Assert.AreSame(connections.ReceivingClient, resultAllowedConnection);
			}
		}

		[Test]
		public void AddressAllowedAfterBlacklistEntryExpires()
		{
			using (var connections = new ConnectedTcpClientPair())
			{
				sut.In_InvalidAddress(connections.ReceivingClient.Client.RemoteEndPoint);
				Thread.Sleep(4000);
				
				sut.In_Connection(connections.ReceivingClient);

				Assert.IsTrue(SpinWait.SpinUntil(() => resultAllowedConnection != null, 1000));
				Assert.AreSame(connections.ReceivingClient, resultAllowedConnection);
			}
		}
	}
}
